/*
 * Copyright © 2018 www.noark.xyz All Rights Reserved.
 *
 * 感谢您选择Noark框架，希望我们的努力能为您提供一个简单、易用、稳定的服务器端框架 ！
 * 除非符合Noark许可协议，否则不得使用该文件，您可以下载许可协议文件：
 *
 *        http://www.noark.xyz/LICENSE
 *
 * 1.未经许可，任何公司及个人不得以任何方式或理由对本框架进行修改、使用和传播;
 * 2.禁止在本项目或任何子项目的基础上发展任何派生版本、修改版本或第三方版本;
 * 3.无论你对源代码做出任何修改和改进，版权都归Noark研发团队所有，我们保留所有权利;
 * 4.凡侵犯Noark版权等知识产权的，必依法追究其法律责任，特此郑重法律声明！
 */
package xyz.noark.network.rpc.shuttle;

import java.io.Serializable;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static xyz.noark.log.LogHelper.logger;

/**
 * Shuttle玩家管理器，存档玩家路由信息，有状态RPC使用这个类来管理玩家在不在线判定
 *
 * @author 小流氓[176543888@qq.com]
 * @since 4.0
 */
class ShuttlePlayerManager {
    /**
     * 玩家路由信息记录，playerId -> ShuttleRouteInfo
     */
    private static final ConcurrentHashMap<Serializable, ShuttlePlayerRoute> playerRoutMap = new ConcurrentHashMap<>();

    private ShuttlePlayerManager() {
    }

    /**
     * 判定一个玩家当前是否在线. * * @param playerId 玩家ID * @return 如果玩家在线则返回true, 否则返回false.
     */
    public static boolean isOnline(Serializable playerId) {
        return playerRoutMap.containsKey(playerId);
    }

    /**
     * 统计当前在线玩家数量. * * @return 在线玩家数量
     */
    public static int statOnlinePlayerNum() {
        return playerRoutMap.size();
    }

    /**
     * 获取所有在线玩家ID集合. * * @return 玩家ID集合
     */
    public static Set<Serializable> getOnlinePlayerIdList() {
        return playerRoutMap.keySet();
    }

    /**
     * 设置玩家路由信息 * * @param playerId 玩家唯一ID * @param prevServerUid 上一个节点UID，无则为0 * @param nextServerUid 下一个节点UID，无则为0
     */
    public static void setRoute(Serializable playerId, int prevServerUid, int nextServerUid) {
        playerRoutMap.put(playerId, new ShuttlePlayerRoute(playerId, prevServerUid, nextServerUid));
        logger.info("玩家路由设置: playerId={}, prev={}, next={}", playerId, prevServerUid, nextServerUid);
    }

    /**
     * 获取玩家路由信息
     */
    public static ShuttlePlayerRoute getRoute(Serializable playerId) {
        return playerRoutMap.get(playerId);
    }

    /**
     * 获取玩家的上一个节点 UID
     */
    public static int getPrevServerUid(Serializable playerId) {
        ShuttlePlayerRoute info = getRoute(playerId);
        return info != null ? info.getPrevServerUid() : 0;
    }

    /**
     * 获取玩家的下一个节点 UID
     */
    public static int getNextServerUid(Serializable playerId) {
        ShuttlePlayerRoute info = getRoute(playerId);
        return info != null ? info.getNextServerUid() : 0;
    }

    /**
     * 更新下一个节点
     */
    public static void updateNextServerUid(Serializable playerId, int nextServerUid) {
        ShuttlePlayerRoute info = getRoute(playerId);
        if (info != null) {
            info.setNextServerUid(nextServerUid);
            logger.info("玩家路由更新: playerId={}, prev={}, next={}", playerId, info.getPrevServerUid(), nextServerUid);
        }
    }

    /**
     * 移除玩家路由（玩家登出时调用）
     */
    public static ShuttlePlayerRoute removeRoute(Serializable playerId) {
        ShuttlePlayerRoute removed = playerRoutMap.remove(playerId);
        if (removed != null) {
            logger.info("路由删除: playerId={}, prev={}, next={}", playerId, removed.getPrevServerUid(), removed.getNextServerUid());
        }
        return removed;
    }
}